package com.jin.webvideo.parser;

import com.jin.webvideo.service.ConfigService;
import com.jin.webvideo.util.consts.ConfigConst;
import com.jin.webvideo.util.base.StringUtil;
import org.graalvm.polyglot.Context;
import org.graalvm.polyglot.Engine;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.Assert;
import org.springframework.web.context.ServletContextAware;

import javax.servlet.ServletContext;
import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStream;
import java.lang.reflect.Field;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.HashMap;
import java.util.Map;
@Component
public class ParserScriptPropertites implements ServletContextAware {
    @Autowired
    private ConfigService service;
    private String srciptLocation;
    private String mappingPath;
    private Context.Builder builder;

    public Context.Builder createBuilder() {
        return builder;
    }

    public String getMappingPath() {
        return mappingPath;
    }

    public String getSrciptLocation() {
        return srciptLocation;
    }

    @Override
    public void setServletContext(ServletContext servletContext) {
        if (builder == null){
            try {
                builder = initBuilder();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        initMappingInfo();
        Assert.notNull(builder, "builder is null");
        Assert.isTrue(!StringUtil.isEmpty(srciptLocation), "srciptLocation is null or empty");
        Assert.isTrue(!StringUtil.isEmpty(mappingPath) && !"/**".equals(mappingPath), "mappingPath is Illegal string");
    }
    private void initMappingInfo(){
        Map<String, String> map = service.configMapByGroupId(ConfigConst.PARSERSCRIPT_CONFIG);
        this.srciptLocation = map.get(ConfigConst.ATTR_CONFIG_SCRIPTLOCATION);
        this.mappingPath = map.get(ConfigConst.ATTR_CONFIG_MAPPINGPATH);
    }
    private Context.Builder initBuilder() throws Exception {
        Map<String, String> config = service.configMapByGroupId(ConfigConst.CONTEXTBUILDER_CONFIG);
        Engine engine = Engine.create();
        Map<String, String> options = new HashMap<>();
        options.put("js.commonjs-require-cwd", config.get("currentWorkingDirectory"));
        options.put("js.commonjs-require", "true");
        Context.Builder builder = Context.newBuilder().options(options).engine(engine);
        Field[] fields = Context.Builder.class.getDeclaredFields();
        for (Field field : fields){
            field.setAccessible(true);
            String name = field.getName();
            String value = config.get(name);
            if (value == null || value.isEmpty()){
                continue;
            }
            Class type = field.getType();
            Object obj = cast(value, type);
            field.set(builder, obj);
        }
        return builder;
    }
    private <T> Object cast(String value, Class<T> clazz) throws Exception {
        Object rst = null;
        if (Boolean.class.isAssignableFrom(clazz) || boolean.class.isAssignableFrom(clazz)){
            rst = Boolean.valueOf(value);
        }
        else if (Path.class.isAssignableFrom(clazz)){
            rst = Paths.get(value);
        }
        else if (OutputStream.class.isAssignableFrom(clazz)){
            File file = new File(value);
            if (!file.exists()){
                file.createNewFile();
            }
            rst = new FileOutputStream(file);
        }
        return rst;
    }
}
